package org.example.mall4j.Filter;

import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.example.mall4j.Handler.LoginFailedHandler;
import org.example.mall4j.Service.UserService;
import org.example.mall4j.Utils.RedisCache;
import org.example.mall4j.Utils.TokenUtil;
import org.example.mall4j.common.CustomerAuthenionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;

@Data
@Component("checkTokenFilter")
@EqualsAndHashCode(callSuper=false)
public class CheckTokenFilter extends OncePerRequestFilter {
    @Value("${hrfan.login.url}")
    private String loginUrl;

    @Autowired
    private LoginFailedHandler loginFailureHandler;

    @Autowired
    private UserService userService;
    @Resource
    private RedisCache redisCache;
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        //获取请求的url(读取配置文件的url)
        String url = httpServletRequest.getServletPath();
        if (StringUtils.contains(httpServletRequest.getServletPath(), "swagger")
                || StringUtils.contains(httpServletRequest.getServletPath(), "webjars")
                || StringUtils.contains(httpServletRequest.getServletPath(), "profile")
                || StringUtils.contains(httpServletRequest.getServletPath(), "swagger-ui")
                || StringUtils.contains(httpServletRequest.getServletPath(), "swagger-resources")
                || StringUtils.contains(httpServletRequest.getServletPath(), "csrf")
                || StringUtils.contains(httpServletRequest.getServletPath(), "favicon")
                || StringUtils.contains(httpServletRequest.getServletPath(), "user")
                || StringUtils.contains(httpServletRequest.getServletPath(), "getImageCode")) {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        }
        else if (StringUtils.equals(url,loginUrl))
        {
            // 是登录请求放行
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        }
        else {
            System.out.println(url);
            try {
                //token验证（如果不是登录请求 验证token）
                if(!url.equals(loginUrl)){
                    System.out.println(" ValidToken ");
                    validateToken(httpServletRequest);
                }
            }catch (AuthenticationException e){
                loginFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
                return;
            }
            filterChain.doFilter(httpServletRequest,httpServletResponse);
        }
    }
    //token验证
    private void validateToken(HttpServletRequest request){
        //从请求的头部获取token
        String token = request.getHeader("token");
        System.out.println(token);
        //如果请求头部没有获取到token，则从请求参数中获取token
        if(StringUtils.isEmpty(token)){
            token = request.getParameter("token");
        }
        if (StringUtils.isEmpty(token)){
            // 请求参数中也没有 那就从redis中进行获取根据ip地址取
            token = redisCache.getCacheObject(request.getRemoteAddr());
        }
        if(StringUtils.isEmpty(token)){
            throw new CustomerAuthenionException("不存在token！");
        }
        //解析token
        String username = TokenUtil.getUserFromToken(token);

        if(StringUtils.isEmpty(username)){
            System.out.println("token解析失败!");
            throw new CustomerAuthenionException("token解析失败!");
        }
        //获取用户信息
        UserDetails user = userService.loadUserByUsername(username);
        if(user == null){
            System.out.println("token验证失败!");
            throw new CustomerAuthenionException("token验证失败!");
        }
        //验证用户
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user,null,user.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        //设置到spring security上下文
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
}

